#include "scriptmanager.h"
#include "workbench.h"
#include "scriptfunctions.h"
#include "treebuilder.h"
#include "scriptapplication.h"
#include "treewidgetiterator.h"
#include "datatreehelper.h"
#include "../network/communicator.h"
#ifdef Q_MOBILITY
    #include "location.h"
#endif
#include <QtScript>
#include <QMessageBox>
#include <QScriptEngine>
#include <QList>
#include <QTextStream>
#include <defines.h>
#include <QScriptProgram>
#include <QtGui/QMainWindow>

ScriptManager* ScriptManager::m_instance = 0;

ScriptManager::ScriptManager()
{
#if !defined(QT_NO_SCRIPTTOOLS)
    debugger.attachTo(&m_scriptEngine);
    debugWindow = debugger.standardWindow();
    debugWindow->resize(1024, 640);
#endif
}

void ScriptManager::initScriptLibrary()
{
    scriptLibraryPaths();
    initScriptFunctions();
    registerScriptObjects();
}

void ScriptManager::scriptLibraryPaths()
{
    QStringList list = QApplication::libraryPaths();
//    list << "/home/cher/qtscriptgenerator.x86/plugins/";
//    list << "/home/night/qt/qtbindings/";
#ifdef Q_OS_ANDROID
    list << "/data/local/";
#else
    list << "c:/Qt/qtscriptgeneratorVS/plugins/";
#endif
    QApplication::setLibraryPaths(list);
    QStringList extensions;
    extensions << "qt.core"
               << "qt.gui"
//                   << "qt.xml"
//                   << "qt.svg"
//                   << "qt.network"
               << "qt.sql"
//                   << "qt.opengl"
//                   << "qt.webkit"
//                   << "qt.xmlpatterns"
               << "qt.uitools";
    QStringList failExtensions;

    foreach (const QString &ext, extensions) {
        QScriptValue ret = m_scriptEngine.importExtension(ext);
        if (ret.isError())
            failExtensions.append(ext);
    }
}

void ScriptManager::initScriptFunctions()
{
    m_scriptEngine.globalObject().setProperty("msgBox",m_scriptEngine.newFunction(msgBox));    
}

void ScriptManager::loadScriptFile(QString scriptname)
{
    QFile file(scriptname);
    if (file.open(QFile::ReadOnly)) {
        QTextStream in(&file);
        in.setCodec("UTF-8");
        QString script = in.readAll();
        QScriptSyntaxCheckResult syntaxResalt = m_scriptEngine.checkSyntax(script);
        if( syntaxResalt.state() == QScriptSyntaxCheckResult::Valid ) {
            QScriptProgram program(script);
            file.close();
            QScriptValue result = m_scriptEngine.evaluate(program);

            if (result.isError()) {
                QMessageBox::critical(0, "Evaluating error", result.toString(), QMessageBox::Yes);
            }
        } else { // SyntaxError
            QString errorMsg;
            scriptname = scriptname.right( scriptname.length() - scriptname.lastIndexOf('/') -1);
            errorMsg += "<b>Script:</b> " + scriptname + "<br>";
            errorMsg += "<b>Line:</b> " + QString::number(syntaxResalt.errorLineNumber()) + " <br>";
            errorMsg += "<b>Column:</b> " + QString::number(syntaxResalt.errorColumnNumber()) + "<br>";
            errorMsg += "<b>Error message:</b><br>" + syntaxResalt.errorMessage();
            QMessageBox::critical(0, "Syntax error", errorMsg ,QMessageBox::Ok);
        }
    } else {
        QMessageBox::critical(0, "File open error", "Can not open the script file",  QMessageBox::Yes);
    }
}

ScriptManager * ScriptManager::instance()
{
    if(m_instance == 0) {
        m_instance = new ScriptManager();
    }
    return m_instance;
}
QScriptValue stubConstructor(QScriptContext *, QScriptEngine *engine)
{
    return engine->newQObject(new QObject(), QScriptEngine::ScriptOwnership);
}

void ScriptManager::registerScriptObjects()
{
    QScriptValue workbench = m_scriptEngine.newQObject(Workbench::instance());
    workbench.setProperty("version", Workbench::instance()->project()->property(XML_VERSION).toString());
    m_scriptEngine.globalObject().setProperty("workbench", workbench);

    QScriptValue appProperty = m_scriptEngine.newQObject(ScriptApplication::instance());
    m_scriptEngine.globalObject().setProperty("app", appProperty);

    QScriptValue comProperty = m_scriptEngine.newQObject(Communicator::instance());
    m_scriptEngine.globalObject().setProperty("communicator", comProperty);

    QScriptValue ct = m_scriptEngine.newFunction(treeBuilderConstructor);
    m_scriptEngine.globalObject().setProperty("SqlTreeBuilder", ct);

#ifdef Q_MOBILITY
    QScriptValue loc = m_scriptEngine.newFunction(locationConstructor);
    m_scriptEngine.globalObject().setProperty("Location", loc);
#else
    m_scriptEngine.globalObject().setProperty("Location", m_scriptEngine.newFunction(stubConstructor));
#endif

    QScriptValue dataTreeCtor = m_scriptEngine.newFunction(dataTreeConstructor);
    m_scriptEngine.globalObject().setProperty("DataTreeHelper", dataTreeCtor);

    QScriptValue treeIterator = m_scriptEngine.newFunction(treeWidgetIterator);
    m_scriptEngine.globalObject().setProperty("TreeWidgetIterator", treeIterator);

    QScriptValue sqlModel = m_scriptEngine.newFunction(sqlTableModelCtor);
    m_scriptEngine.globalObject().setProperty("SqlTableModel", sqlModel);
}

void ScriptManager::invokeFunction(const QString &funcName)
{
    QScriptValue func = m_scriptEngine.globalObject().property(funcName);
    func.call();
}



